/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.engine.common;

import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.api.lcp.ILcpFactory;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.beenum.BETriggerTimePointType;
import com.inspur.edp.bef.bizentity.beenum.RequestNodeTriggerType;
import com.inspur.edp.bef.bizentity.common.BefDtBeanUtil;
import com.inspur.edp.bef.bizentity.operation.BizAction;
import com.inspur.edp.bef.bizentity.operation.BizMgrAction;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.TccSettingElement;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.bef.core.be.BENodeEntity;
import com.inspur.edp.bef.engine.BefCoreExceptionBase;
import com.inspur.edp.bef.engine.ErrorCodes;
import com.inspur.edp.bef.engine.core.be.EngineBusinessEntity;
import com.inspur.edp.bef.engine.core.be.EngineChildEntity;
import com.inspur.edp.bef.engine.entity.AssociationInfo;
import com.inspur.edp.bef.spi.action.AbstractManagerAction;
import com.inspur.edp.cdf.component.api.service.ComponentInvokeService;
import com.inspur.edp.cef.api.dataType.entity.ICefEntityContext;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.*;
import com.inspur.edp.cef.designtime.api.util.MetadataUtil;
import com.inspur.edp.cef.entity.condition.*;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IValuesContainer;
import com.inspur.edp.cef.entity.entity.dynamicProp.DynamicPropSetImpl;
import com.inspur.edp.cef.spi.common.UdtManagerUtil;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.entityaction.CefDataTypeAction;
import com.inspur.edp.cef.spi.util.ExpressionUtil;
import com.inspur.edp.commonmodel.engine.api.common.CMEngineUtil;
import com.inspur.edp.commonmodel.engine.core.common.CMUtil;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.metadata.rtcustomization.api.CustomizationRtService;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.entity.IUdtData;
import io.iec.edp.caf.common.JSONSerializer;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class GspBizEntityUtil extends CMUtil {
    private static ComponentInvokeService componentInvokeService = SpringBeanUtils.getBean(ComponentInvokeService.class);

    public static AbstractManagerAction instantiateMgrAction(
            GspBusinessEntity be, String actionCode, IBEManagerContext context, Object... pars) {
        Objects.requireNonNull(actionCode, "actionCode");
        Objects.requireNonNull(be, "be");

        BizMgrAction op =
                (BizMgrAction)
                        be.getBizMgrActions().stream()
                                .filter(item -> item.getCode().equals(actionCode))
                                .findFirst()
                                .orElse(null);
        if (op == null) {
            throwMgrActionNotFound(be, actionCode);
        }
        return instantiateBEMgrOperation(be, op, AbstractManagerAction.class, context, pars);
    }

    public static CefDataTypeAction instantiateBizAction(
            GspBizEntityObject note, String actionCode, ICefEntityContext context, Object... pars) {
        Objects.requireNonNull(actionCode, "actionCode");
        Objects.requireNonNull(note, "note");
        BizAction op = null;

//      GspBizEntityObject obj = be.getAllNodes().stream().filter(
//          item-> item.getCode().equals(context.getCode())
//      ).findFirst().orElse(null);
//      if(obj == null)
//        throwMgrActionNotFound(be, actionCode);
        op = (BizAction) note.getBizActions().stream().filter(
                item -> item.getCode().equals(actionCode)
        ).findFirst().orElse(null);
        if (op == null)
            throwBizActionNotFound(note, actionCode);
        return instantiateBEBizOperation(op, CefDataTypeAction.class, context, pars);
    }

    public static <T> T instantiateBEMgrOperation(
            GspBusinessEntity be, BizOperation op, Class<T> clazz, IBEManagerContext context, Object... pars) {
        CustomizationRtService mdService = BefDtBeanUtil.getCustomizationRtService();
        GspComponent metadata = CMEngineUtil.getMetadataContent(op.getComponentId());
        if (metadata == null) {
            throwBizOperationCompNotFound(op);
        }
        String typeName = metadata.getMethod().getClassName();
        try {
            if (BizOperationUtil.isBuildInAction(op.getComponentId())) {
                return (T) BizOperationUtil.getInstance(be, op, context, metadata, pars);
            } else {
                Object[] args = new Object[pars != null ? pars.length + 1 : 1];
                args[0] = context;
                if (pars != null) {
                    System.arraycopy(pars, 0, args, 1, pars.length);
                }
                return getComponentClass(op.getComponentId(), Arrays.asList(args));
//        Constructor constructor = Arrays.stream(Class.forName(typeName).getConstructors())
//            .filter(ctor -> ctor.getParameterCount() == args.length).findFirst().orElse(null);
//        if(constructor== null){
//          throw new RuntimeException("构件类[" + typeName + "]上找不到"+args.length+"个参数的构造函数, 请传入匹配的参数");
//        }
//        return (T) constructor.newInstance(args);
            }
        } catch (Exception var2) {
            throw new BefCoreExceptionBase(var2);
        }
    }

    private static <T> T instantiateBEBizOperation(
            BizOperation op, Class<T> clazz, ICefEntityContext context, Object... pars) {
        //    GspComponent metadata = CMEngineUtil.getMetadataContent(op.getComponentId());
//    if (metadata == null ) {
//      throwBizOperationCompNotFound(op);
//    }
//    String typeName = metadata.getMethod().getClassName();

        Object[] args = new Object[pars != null ? pars.length + 1 : 1];
        args[0] = context;
        if (pars != null) {
            System.arraycopy(pars, 0, args, 1, pars.length);
        }
        return (T) componentInvokeService.getInstance(op.getComponentId(), Arrays.asList(args));

//    Constructor constructor = null;
//    try {
//      constructor = Class.forName(typeName).getConstructors()[0];
//    } catch (ClassNotFoundException e) {
//      e.printStackTrace();
//    }
//    try {
//      return (T) constructor.newInstance(args);
//    } catch (InstantiationException | IllegalAccessException |InvocationTargetException var2) {
//      throw new RuntimeException(var2);
//    }
    }

    public static Constructor getConstructor(String compId, Class... parTypes) {
        GspComponent beComponent = CMEngineUtil.getMetadataContent(compId);
        try {
            Class clazz = Class.forName(beComponent.getMethod().getClassName());
            return clazz.getConstructor(parTypes);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            throw new BefCoreExceptionBase(e);
        }
    }

    /**
     * @param compId          构件ID
     * @param constructorArgs 构造函数参数
     * @param <T>             返回值类型
     * @return 构件类
     */
    public static <T> T getComponentClass(String compId, List<Object> constructorArgs) {
        return (T) componentInvokeService.getInstance(compId, constructorArgs);
    }

    public static boolean equals(IGspCommonElement element, Object value1, Object value2) {
        if (element.getMDataType() == GspElementDataType.Binary && value1 != null
                && value1 instanceof byte[] && value2 != null && value2 instanceof byte[]) {
            return Arrays.equals((byte[]) value1, (byte[]) value2);
        }
        if (value1 == null) {
            return value2 == null;
        }
        return value1.equals(value2);
    }

    public static boolean canTrigger(Map<BETriggerTimePointType, EnumSet<RequestNodeTriggerType>> tiggerPoints, BETriggerTimePointType tiggerPoint) {
        EnumSet<RequestNodeTriggerType> requestNodeTriggerTypes = tiggerPoints.get(tiggerPoint);
        return requestNodeTriggerTypes != null && !requestNodeTriggerTypes.isEmpty();
    }

    public static void throwElementNotFound(IGspCommonObject node, String labelId) {
        throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1002, node.getCode(), labelId);
    }

    public static void throwMgrActionNotFound(GspBusinessEntity be, String actionCode) {
        throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1003, be.getCode(), actionCode);
    }

    public static void throwBizActionNotFound(GspBizEntityObject note, String actionCode) {
        throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1004, note.getCode(), actionCode);
    }

    public static void throwBizOperationCompNotFound(BizOperation op) {
        throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1005, op.getCode(), op.getComponentName());
    }

    public static void throwNoTccComp(GspBizEntityObject node, TccSettingElement setting) {
        throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1006, node.getBelongModel().getCode(), node.getCode(), setting.getCode());
    }

    public static String getString(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return "";
    }

    public static Integer getInteger(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return Integer.valueOf(0);
    }

    public static BigDecimal getDecimal(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return new BigDecimal("0.0");
    }

    public static Boolean getBoolean(boolean isDefaultNull) {
        if (isDefaultNull)
            return null;
        return Boolean.valueOf(false);
    }

    public static void initBasicType(IGspCommonField element, IEntityData data, boolean isDefaultNull) {
        switch (element.getMDataType()) {
            case String:
            case Text:
                data.setValue(element.getLabelID(), getString(isDefaultNull));
                break;
            case Integer:
                data.setValue(element.getLabelID(), getInteger(isDefaultNull));
                break;
            case Decimal:
                data.setValue(element.getLabelID(), getDecimal(isDefaultNull));
                break;
            case Boolean:
                data.setValue(element.getLabelID(), getBoolean(isDefaultNull));
                break;
        }
    }

    public static void initBeDataValue(IGspCommonObject node, IEntityData data,
                                       Predicate<IGspCommonField> predicate, CefEntityResInfoImpl resInfo) {
        for (IGspCommonField field : node.getContainElements()) {
            if (predicate != null && !predicate.test(field)) {
                continue;
            }

            if (node.getIDElement() == field) {
                continue;
            }
            boolean isDefaultNull = ((GspBizEntityElement) field).getIsDefaultNull();
            if (field.getIsUdt()) {
                initUdtValue(field, data, resInfo, isDefaultNull);
                continue;
            }
            switch (field.getObjectType()) {
                case None:
                    initBasicType(field, data, isDefaultNull);
                    break;
                case Enum:
                    initEnumValue(field, data, isDefaultNull);
                    break;
                case DynamicProp:
                    data.setValue(field.getLabelID(), new DynamicPropSetImpl());
                    break;
                case Association:
                    if (field.getObjectType() == GspElementObjectType.Association && field
                            .getChildAssociations() != null &&
                            !field.getChildAssociations().isEmpty()) {
                        data.setValue(field.getLabelID(), new AssociationInfo((GspAssociation) field
                                .getChildAssociations().get(0)));
                    }
                    break;
            }
        }
    }

    private static void initUdtValue(IGspCommonField field, IEntityData data, CefEntityResInfoImpl resInfo, boolean isDefaultNull) {
        String udtId = field.getUdtID();
        UnifiedDataTypeDef udtContent = (UnifiedDataTypeDef) getMetaData(udtId).getContent();
        String udtConfigId = getUdtConfigId(field, resInfo);
        if (udtContent instanceof ComplexDataTypeDef) {
            data.setValue(field.getLabelID(), UdtManagerUtil.getUdtFactory().createManager(udtConfigId).createDataType());
            return;
        }
        if (udtContent instanceof SimpleDataTypeDef) {
            initSimpleUdt(field, data, isDefaultNull, udtConfigId);
        }
    }

    private static void initSimpleUdt(IGspCommonField field, IEntityData data, boolean isDefaultNull, String udtConfigId) {
        switch (field.getObjectType()) {
            case None:
                initUdtBaicValue(field, data, isDefaultNull, udtConfigId);
                break;
            case Enum:
                initUdtEnumValue(field, data, isDefaultNull, udtConfigId);
                break;
            case Association:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            case DynamicProp:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            default:
                throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1007, String.valueOf(field.getObjectType()));
        }
    }

    private static void initUdtEnumValue(IGspCommonField field, IEntityData data, boolean isDefaultNull, String udtConfigId) {
        data.setValue(field.getLabelID(), isDefaultNull ? UdtManagerUtil.createData(udtConfigId, null) : UdtManagerUtil.createData(udtConfigId));
    }

    private static void initUdtBaicValue(IGspCommonField field, IEntityData data, boolean isDefaultNull, String udtConfigId) {
        switch (field.getMDataType()) {
            case String:
                data.setValue(field.getLabelID(), isDefaultNull ? UdtManagerUtil.createData(udtConfigId) : UdtManagerUtil.createData(udtConfigId, getString(isDefaultNull)));
                break;
            case Text:
                data.setValue(field.getLabelID(), isDefaultNull ? UdtManagerUtil.createData(udtConfigId) : UdtManagerUtil.createData(udtConfigId, getString(isDefaultNull)));
                break;
            case Integer:
                data.setValue(field.getLabelID(), isDefaultNull ? UdtManagerUtil.createData(udtConfigId) : UdtManagerUtil.createData(udtConfigId, getInteger(isDefaultNull)));
                break;
            case Decimal:
                data.setValue(field.getLabelID(), isDefaultNull ? UdtManagerUtil.createData(udtConfigId) : UdtManagerUtil.createData(udtConfigId, getDecimal(isDefaultNull)));
                break;
            case Boolean:
                data.setValue(field.getLabelID(), isDefaultNull ? UdtManagerUtil.createData(udtConfigId) : UdtManagerUtil.createData(udtConfigId, getBoolean(isDefaultNull)));
                break;
            case Date:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            case DateTime:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            case Binary:
                data.setValue(field.getLabelID(), UdtManagerUtil.createData(udtConfigId));
                break;
            default:
                throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1008, String.valueOf(field.getMDataType()));
        }
    }

    private static GspMetadata getMetaData(String metaId) {
        GspMetadata udtMetadata;
        try {
            udtMetadata = MetadataUtil.getCustomRTMetadata(metaId);
        } catch (Exception var4) {
            throw new BefCoreExceptionBase(var4, ErrorCodes.BEF_ENGINE_1009, metaId);
        }
        return udtMetadata;
    }

    public static void initEnumValue(IGspCommonField element, IEntityData data, boolean isDefaultNull) {
        if (isDefaultNull) {
            data.setValue(element.getLabelID(), null);
        } else {
            GspEnumValue defaultValue = element.getContainEnumValues().stream()
                    .filter(item -> item.getIsDefaultEnum()).findFirst()
                    .orElse(element.getContainEnumValues().get(0));
            data.setValue(element.getLabelID(), defaultValue.getValue());
        }
    }

    /**
     * 默认值
     *
     * @param node 实体节点
     * @param data 数据data
     */
    public static void assignDefaultValue(GspBizEntityObject node, IEntityData data) {
//        IGspCommonObject node = entity.getMainObject();
        for (IGspCommonField field : node.getContainElements()) {
            if (StringUtils.isEmpty(field.getDefaultValue())) {
                continue;
            }
            try {
                // udt 单独处理
                if (field.getIsUdt()) {
                    dealUdtDefaultValue(field, data);
                    continue;
                }
            } catch (Throwable e) {
                throw new BefCoreExceptionBase(new Exception(e), ErrorCodes.BEF_ENGINE_1014,
                        node.getBelongModel().getID(), node.getBelongModel().getCode(),
                        node.getBelongModel().getName(), node.getCode(), field.getCode(),
                        field.getDefaultValue());
            }
            try {
                switch (field.getObjectType()) {
                    case Enum:
                        data.setValue(field.getLabelID(), field.getDefaultValue());
                        break;
                    case None:
                        assignDefaultValue_NoneObjType(field, data);
                        break;
                    case Association:
                        assignDefaultValue_AssociationType(field, data);
                    default:
                }
                // TODO: 动态属性初始值
            } catch (Throwable e) {
                if (e instanceof BefCoreExceptionBase) {
                    throw e;
                }
                throw new BefCoreExceptionBase(new Exception(e), ErrorCodes.BEF_ENGINE_1015,
                        node.getBelongModel().getID(), node.getBelongModel().getCode(),
                        node.getBelongModel().getName(), node.getCode(), field.getCode(),
                        field.getDefaultValue());
            }
        }
    }

    public static void assignChildObjectDefaultValue(GspBizEntityObject node, IEntityData data, EngineChildEntity engineChildEntity) {
//        IGspCommonObject node = entity.getMainObject();
        Map<String, String> expressionValueMap = new HashMap<>(2);
        for (IGspCommonField field : node.getContainElements()) {
            if (StringUtils.isEmpty(field.getDefaultValue())) {
                continue;
            }
            try {
                // udt 单独处理
                if (field.getIsUdt()) {
                    dealUdtDefaultValue(field, data);
                    continue;
                }
            } catch (Throwable e) {
                throw new BefCoreExceptionBase(new Exception(e), ErrorCodes.BEF_ENGINE_1014,
                        node.getBelongModel().getID(), node.getBelongModel().getCode(),
                        node.getBelongModel().getName(), node.getCode(), field.getCode(),
                        field.getDefaultValue());
            }
            try {
                switch (field.getObjectType()) {
                    case Enum:
                        data.setValue(field.getLabelID(), field.getDefaultValue());
                        break;
                    case None:
                        //目前仅表达式类型的默认值需要用到expressionValueMap，因此增加默认值类型的条件，以提升性能
                        if (expressionValueMap.size() == 0 && field.getDefaultValueType() == ElementDefaultVauleType.Expression) {
                            setEvaluatorMap((BENodeEntity) engineChildEntity.getParent(), expressionValueMap);
                        }
                        assignChildDefaultValue_NoneObjType(field, data, expressionValueMap);
                        break;
                    case Association:
                        assignDefaultValue_AssociationType(field, data);
                    default:
                }
                // TODO: 动态属性初始值
            } catch (Throwable e) {
                throw new BefCoreExceptionBase(new Exception(e), ErrorCodes.BEF_ENGINE_1015,
                        node.getBelongModel().getID(), node.getBelongModel().getCode(),
                        node.getBelongModel().getName(), node.getCode(), field.getCode(),
                        field.getDefaultValue());
            }
        }
    }

    /**
     * 关联默认值
     *
     * @param field 字段
     * @param data  数据data
     */
    private static void assignDefaultValue_AssociationType(IGspCommonField field, IEntityData data) {
        if (field.getChildAssociations() == null || field.getChildAssociations().size() < 1) {
            return;
        }
        // 关联带出默认值 检索 ID
        String associationDefaultValue = getSimplyDefaultValueString(field);
        GspAssociation associationInfo = field.getChildAssociations().get(0);
        GspFieldCollection refFields = associationInfo.getRefElementCollection();
        if (refFields == null || refFields.size() < 1) {
            return;
        }
        List<IGspCommonField> refBeField = getRefBeFields(associationInfo);
        if (refBeField == null) {
            return;
        }
        IEntityData resultData = getAssoData(associationInfo, refFields, associationDefaultValue);
        if (resultData == null) {
            throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1010, field.getName(), associationDefaultValue);
        }
        Map<String, String> refFieldsLabId = getRefFieldsLabelID(refFields, refBeField);
        AssociationInfo fieldData = (AssociationInfo) data.getValue(field.getLabelID());

        if (refFieldsLabId.size() == 0) {
            return;
        }
        for (Map.Entry<String, String> idem : refFieldsLabId.entrySet()) {
            fieldData.setValue(idem.getKey(), resultData.getValue(idem.getValue()));
        }
        for (IGspCommonField iGspCommonField : refBeField) {
            if (iGspCommonField.getObjectType().equals(GspElementObjectType.Association)) {
                setChildAssInfo(refFields, iGspCommonField, fieldData, resultData);
            }
        }
        fieldData.setValue(field.getLabelID(), associationDefaultValue);
    }

    /**
     * Udt默认值 目前支持：关联
     *
     * @param field 字段
     * @param data  数据
     */
    private static void dealUdtDefaultValue(IGspCommonField field, IEntityData data) {
        String udtId = field.getUdtID();
        UnifiedDataTypeDef beComponent = CMEngineUtil.getMetadataContent(udtId);
        if (beComponent == null) {
            return;
        }

        if (beComponent instanceof SimpleDataTypeDef) {
            // 单值UDT
            // 关联
            if (((SimpleDataTypeDef) beComponent).getObjectType() == GspElementObjectType.Association) {
                assignDefaultValue_AssociationSimpleUdtObjType(field, data, beComponent);
            }
        } else {
            // 多值UDT
            assignDefaultValue_ComplexUdtObjType(field, data, beComponent);
        }

    }

    /**
     * 多值UDT赋默认值
     *
     * @param field              字段
     * @param data               数据data
     * @param unifiedDataTypeDef udt元数据信息
     */
    private static void assignDefaultValue_ComplexUdtObjType(IGspCommonField field, IEntityData data,
                                                             UnifiedDataTypeDef unifiedDataTypeDef) {

        IGspCommonField udtField = unifiedDataTypeDef.getContainElements().get(0);
        // 默认值,需要进行反序列化
        String defaultValue = getComplexDefaultValueString(field);
        String nameSpace = unifiedDataTypeDef.getApiNamespace().getDefaultNamespace();
        String udtConfigID = getUdtConfigId(unifiedDataTypeDef.getID(), nameSpace);

        IUdtData udtDefaultValue = (IUdtData) UdtManagerUtil.getUdtFactory().createManager(udtConfigID).deserialize(defaultValue);
        List<String> udtPropertyNames = udtDefaultValue.getPropertyNames();
        IUdtData udtData = (IUdtData) data.getValue(field.getLabelID());
        IValuesContainer valuesContainer = (IValuesContainer) udtData;
        for (String fieldName : udtPropertyNames) {
            valuesContainer.setValue(fieldName, udtDefaultValue.getValue(fieldName));
        }
    }

    private static String getComplexDefaultValueString(IGspCommonField field) {
        String defaultValue = field.getDefaultValue();
        if (field.getDefaultValueType() == ElementDefaultVauleType.Expression) {
            Object obj = ExpressionUtil.getExpressionValue(defaultValue);
            if (obj instanceof String) {
                defaultValue = obj.toString();
            }
            throw new BefCoreExceptionBase(ErrorCodes.BEF_ENGINE_1011);
        }
        return defaultValue;
    }

    /**
     * 单值UDT关联字段支持默认值
     *
     * @param field              关联字段
     * @param data               数据
     * @param unifiedDataTypeDef udt信息
     */
    private static void assignDefaultValue_AssociationSimpleUdtObjType(IGspCommonField field, IEntityData data,
                                                                       UnifiedDataTypeDef unifiedDataTypeDef) {
        if (field.getChildAssociations() == null || field.getChildAssociations().size() < 1) {
            return;
        }
        IGspCommonField udtField = unifiedDataTypeDef.getContainElements().get(0);
        // 关联带出默认值 检索 ID
        String associationDefaultValue = getSimplyDefaultValueString(field);
        GspAssociation associationInfo = udtField.getChildAssociations().get(0);
        String refModelId = associationInfo.getRefModelID();
        GspFieldCollection refFields = associationInfo.getRefElementCollection();
        if (refFields == null || refFields.size() < 1) {
            return;
        }
        RetrieveParam param = getRetrieveParam(associationInfo, refFields);
        IStandardLcp lcp = SpringBeanUtils.getBean(ILcpFactory.class).createLcpByBEId(refModelId);
        IEntityData resultData = lcp.retrieve(associationDefaultValue, param).getData();
        List<IGspCommonField> udtRefBeField = getRefBeFields(associationInfo);
        if (udtRefBeField == null) {
            return;
        }
        Map<String, String> refFieldsLabId = getRefFieldsLabelID(refFields, udtRefBeField);
        IUdtData udtData = (IUdtData) data.getValue(field.getLabelID());
        IValuesContainer valuesContainer = (IValuesContainer) udtData;
        IValuesContainer udtInfo = (IValuesContainer) valuesContainer.createValue(udtData.getPropertyNames().get(0));
        for (Map.Entry<String, String> idem : refFieldsLabId.entrySet()) {
            udtInfo.setValue(idem.getKey(), resultData.getValue(idem.getValue()));
        }
        udtInfo.setValue(udtData.getPropertyNames().get(0), associationDefaultValue);
        valuesContainer.setValue(udtData.getPropertyNames().get(0), udtInfo);
    }

    /**
     * 关联默认值
     * 支持表达式和默认值
     *
     * @param field 字段
     * @return 默认值
     */
    private static String getSimplyDefaultValueString(IGspCommonField field) {
        String associationDefaultValue = field.getDefaultValue();
        if (field.getDefaultValueType() == ElementDefaultVauleType.Expression) {
            associationDefaultValue = ExpressionUtil.getExpressionValue(associationDefaultValue).toString();
        }
        return associationDefaultValue;
    }

    /**
     * 获取关联模型-》Object的字段列表
     *
     * @param associationInfo 关联信息
     * @return 关联字段列表
     */
    private static List<IGspCommonField> getRefBeFields(GspAssociation associationInfo) {
        GspBusinessEntity refBe = CMEngineUtil.getMetadataContent(associationInfo.getRefModelID());
        if (refBe == null) {
            return null;
        }
        List<IGspCommonObject> refObjects = refBe.getAllObjectList();
        for (IGspCommonObject obj : refObjects) {
            if (associationInfo.getRefObjectID().equals(obj.getID())) {
                return obj.getContainElements();
            }
        }
        return null;
    }

    /**
     * 获取关联带出字段code
     *
     * @param fields        关联带出字段
     * @param udtRefBeField 关联带出BE字段列表
     * @return 关联带出字段code集合
     */
    private static Map<String, String> getRefFieldsLabelID(GspFieldCollection fields,
                                                           List<IGspCommonField> udtRefBeField) {

        Map<String, String> refFieldIdToLabelId = udtRefBeField.stream().collect(Collectors.toMap(IGspCommonField::getID, IGspCommonField::getLabelID));
        Map<String, String> udtFieldIdToRefFieldId = new HashMap<>();
        for (IGspCommonField field : fields) {
            if (refFieldIdToLabelId.containsKey(field.getRefElementId())) {
                udtFieldIdToRefFieldId.put(field.getLabelID(), refFieldIdToLabelId.get(field.getRefElementId()));
            }
        }

        return udtFieldIdToRefFieldId;
    }

    /**
     * 设置关联检索过滤字段
     *
     * @param associationInfo 关联信息
     * @param refFields       关联带出字段信息
     * @return 过滤字段
     */
    private static RetrieveParam getRetrieveParam(GspAssociation associationInfo, GspFieldCollection refFields) {
        RetrieveParam param = new RetrieveParam();
        String aoosObjectCode = associationInfo.getRefObjectCode();
        RetrieveFilter retrieveFilter = new RetrieveFilter();
        retrieveFilter.setOnlyRetrieveSomeChilds(true);
        EntityFilter entityFilter = new EntityFilter();
        FieldsFilter fieldsFilter = new FieldsFilter();
        entityFilter.setFieldsFilter(fieldsFilter);
        refFields.forEach(field -> fieldsFilter.getFilterFields().add(field.getID()));
        retrieveFilter.getNodeFilters().put(aoosObjectCode, entityFilter);
        param.setRetrieveFilter(retrieveFilter);

        return param;
    }

    /**
     * 获取默认值关联的数据
     * @param associationInfo
     * @param refFields
     * @param associationDefaultValue
     * @return
     */
    private static IEntityData getAssoData(GspAssociation associationInfo, GspFieldCollection refFields, String associationDefaultValue) {
        //关联字段ID
        String assoElementId = associationInfo.getKeyCollection().get(0).getSourceElement();
        // associationInfo.getRefObjectID();
        GspBusinessEntity refBe = CMEngineUtil.getMetadataContent(associationInfo.getRefModelID());
        IGspCommonObject refObject = refBe.findObjectById(associationInfo.getRefObjectID());
        IGspCommonElement refElement = refObject.findElement(assoElementId);

        EntityFilter entityFilter = new EntityFilter();
        FieldsFilter fieldsFilter = new FieldsFilter();
        entityFilter.setFieldsFilter(fieldsFilter);
        refFields.forEach(field -> fieldsFilter.getFilterFields().add(field.getID()));

        List<FilterCondition> filterConditions = FilterConditionBuilder.builder().andEqual(refElement.getLabelID(), associationDefaultValue).build();
        entityFilter.setFilterConditions((ArrayList<FilterCondition>) filterConditions);


        IStandardLcp lcp = SpringBeanUtils.getBean(ILcpFactory.class).createLcpByBEId(associationInfo.getRefModelID());
        List<IEntityData> resultDatas = lcp.query(associationInfo.getRefObjectCode(), entityFilter);
        if(resultDatas == null || resultDatas.size() == 0){
            return null;
        }
        return resultDatas.get(0);
    }


    private static void setChildAssInfo(GspFieldCollection refFields, IGspCommonField iGspCommonField, AssociationInfo fieldData, IEntityData resultData) {
        GspFieldCollection refElementCollection = iGspCommonField.getChildAssociations().get(0).getRefElementCollection();
        for (IGspCommonField refField : refFields) {
            IGspCommonField item = refElementCollection.getItem(refField.getRefElementId());
            if (item == null) {
                continue;
            }
            Object assElementValue = resultData.getValue(iGspCommonField.getLabelID());
            if (assElementValue instanceof IValuesContainer) {
                fieldData.setValue(refField.getLabelID(), ((IValuesContainer) assElementValue).getValue(item.getLabelID()));
            }
            // fieldData.setValue(refField.getLabelID(),assElementValue.getValue(item.getLabelID()));
        }
    }

    private static void setEvaluatorMap(BENodeEntity nodeEntity, Map<String, String> evaluatorMap) {
        if (!nodeEntity.isRoot()) {
            setEvaluatorMap((BENodeEntity) nodeEntity.getParent(), evaluatorMap);
            evaluatorMap.put(nodeEntity.getEntityResInfo().getEntityCode(), JSONSerializer.serialize(nodeEntity.getData()));
        } else {
            evaluatorMap.put(((EngineBusinessEntity) nodeEntity).getNodeCode(), JSONSerializer.serialize(nodeEntity.getData()));
        }
    }
}
